﻿#pragma once

#include "../../MirEnvir/Envir.h"
#include "../../MessageQueue.h"
#include "../../../Shared/Enums.h"
#include "../../../Shared/Data/ItemData.h"
#include "../../MirDatabase/RecipeInfo.h"
#include "NPCPage.h"
#include "../PlayerObject.h"
#include "NPCSegment.h"
#include "../MonsterObject.h"
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include "exceptionhelper.h"
#include "../../../stringhelper.h"
#include "../../../tangible_filesystem.h"

using namespace Server::MirDatabase;
using namespace Server::MirEnvir;
using namespace Server::MirObjects;
namespace S = ServerPackets;

namespace Server::MirObjects
{
    class NPCScript
    {
    protected:
        static Server::MirEnvir::Envir *getEnvir();

        static Server::MessageQueue *getMessageQueue();

    public:
        static NPCScript *Get(int index);

        static NPCScript *GetOrAdd(unsigned int loadedObjectID, const std::string &fileName, NPCScriptType type);

        const int ScriptID;
        const unsigned int LoadedObjectID;
        const NPCScriptType Type;
    protected:
        const std::string FileName;

    public:
        static const std::string MainKey, BuyKey, SellKey, BuySellKey, RepairKey, SRepairKey, RefineKey, RefineCheckKey, RefineCollectKey, ReplaceWedRingKey, BuyBackKey, StorageKey, ConsignKey, MarketKey, CraftKey, GuildCreateKey, RequestWarKey, SendParcelKey, CollectParcelKey, AwakeningKey, DisassembleKey, DowngradeKey, ResetKey, PearlBuyKey, BuyUsedKey, TradeKey, RecipeKey, TypeKey, UsedTypeKey, QuestKey, SpeechKey;


        std::vector<ItemType> Types = std::vector<ItemType>();
        std::vector<ItemType> UsedTypes = std::vector<ItemType>();
        std::vector<UserItem*> Goods = std::vector<UserItem*>();
        std::vector<RecipeInfo*> CraftGoods = std::vector<RecipeInfo*>();

        std::vector<NPCPage*> NPCSections = std::vector<NPCPage*>();
        std::vector<NPCPage*> NPCPages = std::vector<NPCPage*>();

    private:
        NPCScript(unsigned int loadedObjectID, const std::string &fileName, NPCScriptType type);

    public:
        void Load();

        float PriceRate(PlayerObject *player, bool baseRate = false);


        void LoadInfo();
        void ClearInfo();
        void LoadGoods();

    private:
        void ParseDefault(std::vector<std::string> &lines);

        void ParseScript(std::vector<std::string> &lines);

        std::vector<std::string> ParseInsert(std::vector<std::string> &lines);

        std::vector<std::string> ParseInclude(std::vector<std::string> &lines);


        std::vector<NPCPage*> ParsePages(std::vector<std::string> &lines, const std::string &key = MainKey);

        NPCPage *ParsePage(std::vector<std::string> &scriptLines, const std::string &sectionName);

        NPCSegment *ParseSegment(NPCPage *page, std::vector<std::string> &scriptLines);

        void ParseTypes(std::vector<std::string> &lines);
        void ParseGoods(std::vector<std::string> &lines);
        void ParseQuests(std::vector<std::string> &lines);


        void ParseSpeech(std::vector<std::string> &lines);
        void ParseCrafting(std::vector<std::string> &lines);

    public:
        void Call(MonsterObject *monster, const std::string &key);
        void Call(const std::string &key);
        void Call(PlayerObject *player, unsigned int objectID, const std::string &key);

    private:
        void Response(PlayerObject *player, NPCPage *page);

        void ProcessSegment(PlayerObject *player, NPCPage *page, NPCSegment *segment, unsigned int objectID);

        void ProcessSegment(MonsterObject *monster, NPCPage *page, NPCSegment *segment);
        void ProcessSegment(NPCPage *page, NPCSegment *segment);

        void ProcessSpecial(PlayerObject *player, NPCPage *page);

    public:
        void Buy(PlayerObject *player, unsigned long long index, unsigned short count);
        void Sell(PlayerObject *player, UserItem *item);
        void Craft(PlayerObject *player, unsigned long long index, unsigned short count, std::vector<int> &slots);
    };

    enum class NPCScriptType
    {
        Normal,
        Called,
        AutoPlayer,
        AutoMonster,
        Robot
    };
}
